/**
 * Copyright (c) 2010 Moogene
 * All rights reserved
 *
 * This software is the confidential and proprietary information of Moogene.
 * You shall not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the license agreement you entered into
 * with Moogene
 */
package com.moogene.android.engine.action;

import android.view.KeyEvent;

import com.moogene.android.engine.mmi.Book;
import com.moogene.android.engine.util.MooMath;

/**
 * @author Song, jiawei
 * 
 */
public class KeyAnalyse {
	private static final int DOUBLEPRESS_INTERVAL = 5;
	private static final int DOUBLEPRESS_PASS_INTERVAL = 10;
	public static final int GK_INVALID = 0;

	private final int GAME_KEY_COUNT = 14;

	private static KeyAnalyse sKeyAnalyse;

	private int keyCurrent;
	private int keyPressed;
	private int keyReleased;
	private int key;

	private long[] lastPress = new long[GAME_KEY_COUNT];
	private long[] intervalPress = new long[GAME_KEY_COUNT];

	private KeyAnalyse() {
		keyCurrent = 0;
		keyPressed = 0;
		keyReleased = 0;
		key = 0;
	}

	static KeyAnalyse getInstance() {
		if (sKeyAnalyse == null) {
			sKeyAnalyse = new KeyAnalyse();
		}
		return sKeyAnalyse;
	}

	void update() {
		keyPressed = ~key & keyCurrent;
		keyReleased = key & ~keyCurrent;
		key = keyCurrent;
	}

	public boolean onKeyUp(int keyCode) {
		int gameKey = translateKey(keyCode);
		if (gameKey == GK_INVALID) {
			return false;
		}
		keyCurrent &= ~gameKey;
		return true;
	}

	public boolean onKeyDown(int keyCode) {
		int gameKey = translateKey(keyCode);
		if (gameKey == GK_INVALID) {
			return false;
		}
		// keyCurrent |= gameKey;
		if (keyCurrent == 0) {
			keyCurrent = gameKey;
		} else {
			return true;
		}
		int index = MooMath.log2(gameKey);
		intervalPress[index] = Book.sCurPageCounter - lastPress[index];
		lastPress[index] = Book.sCurPageCounter;
		return true;
	}

	private static int translateKey(int keyCode) {
		switch (keyCode) {
		case KeyEvent.KEYCODE_DPAD_UP:
		case KeyEvent.KEYCODE_W:
			return ActKeyEvent.GK_UP;
		case KeyEvent.KEYCODE_DPAD_DOWN:
		case KeyEvent.KEYCODE_X:
			return ActKeyEvent.GK_DOWN;
		case KeyEvent.KEYCODE_DPAD_LEFT:
		case KeyEvent.KEYCODE_A:
			return ActKeyEvent.GK_LEFT;
		case KeyEvent.KEYCODE_DPAD_RIGHT:
		case KeyEvent.KEYCODE_D:
			return ActKeyEvent.GK_RIGHT;
		case KeyEvent.KEYCODE_Q:
			return ActKeyEvent.GK_UPLEFT;
		case KeyEvent.KEYCODE_Z:
			return ActKeyEvent.GK_DOWNLEFT;
		case KeyEvent.KEYCODE_E:
			return ActKeyEvent.GK_UPRIGHT;
		case KeyEvent.KEYCODE_C:
			return ActKeyEvent.GK_DOWNRIGHT;

		case KeyEvent.KEYCODE_DPAD_CENTER:
		case KeyEvent.KEYCODE_S:
		case KeyEvent.KEYCODE_J:
			return ActKeyEvent.GK_A;
		case KeyEvent.KEYCODE_K:
			return ActKeyEvent.GK_B;
		case KeyEvent.KEYCODE_L:
			return ActKeyEvent.GK_C;
		case KeyEvent.KEYCODE_I:
			return ActKeyEvent.GK_D;

		case KeyEvent.KEYCODE_N:
			return ActKeyEvent.GK_LEFT_SOFT;
		case KeyEvent.KEYCODE_M:
			return ActKeyEvent.GK_RIGHT_SOFT;

		default:
			return GK_INVALID;
		}
	}

	boolean isAnyKeyHold() {
		return keyCurrent != 0;
	}

	boolean isAnyKeyPressed() {
		return isKeyPressed(ActKeyEvent.GK_LEFT | ActKeyEvent.GK_RIGHT
				| ActKeyEvent.GK_UP | ActKeyEvent.GK_DOWN
				| ActKeyEvent.GK_UPRIGHT | ActKeyEvent.GK_DOWNRIGHT
				| ActKeyEvent.GK_DOWNLEFT | ActKeyEvent.GK_UPLEFT
				| ActKeyEvent.GK_A | ActKeyEvent.GK_B | ActKeyEvent.GK_C
				| ActKeyEvent.GK_D);
	}

	boolean isKeyDoublePressed(int gameKey) {
		if (!isKeyPressed(gameKey))
			return false;
		int index = MooMath.log2(gameKey);
		if (gameKey == ActKeyEvent.GK_A) {
			return intervalPress[index] < DOUBLEPRESS_PASS_INTERVAL;
		}
		return intervalPress[index] < DOUBLEPRESS_INTERVAL;
	}

	boolean isKeyHold(int gameKey) {
		return (keyCurrent & gameKey) != 0;
	}

	boolean isKeyPressed(int gameKey) {
		return (keyPressed & gameKey) != 0;
	}

	boolean isKeyReleased(int gameKey) {
		return (keyReleased & gameKey) != 0;
	}

}
